
#include <ctype.h>   // For isalpha(), isdigit() ..
#include <time.h>    // For time_t time storage etc.

#include "Core.h"
#include "Util.h"
#include "FlightRecord.h"

namespace AirlineRes
{

FlightRecord::FlightRecord
(
  std::string const&  _flightCode,
  int         const&  _numSeats,
  TimeDate    const&  _time,
	std::string const& _destination
)
{
  ASSERT( LoadRecordData( _flightCode, _numSeats, _time.GetHHMM(), _time.GetDDMMYYYY(), _destination ) == RecordIOResult_Success );
}

Record::RecordIOResult FlightRecord::LoadRecord( std::istream& _stream )
{
  std::string flightCode;
  int numSeats;
  std::string departureTime;
  std::string departureDate;
	std::string destination;

  _stream >> std::skipws;   // Skip whitespace.
  _stream >> m_id >> flightCode >> numSeats >> departureTime >> departureDate >> destination;
  _stream >> std::noskipws; // Reset stream state.

  return LoadRecordData( flightCode, numSeats, departureTime, departureDate, destination );
}

Record::RecordIOResult FlightRecord::WriteRecord( std::ostream& _stream ) const
{
  _stream
    << m_id << " "
    << m_flightCode << " "
    << m_numSeats << " "
    << m_time.GetHHMM() << " "
    << m_time.GetDDMMYYYY() << " "
		<< m_destination << "\n";

  return RecordIOResult_Success;
}

FlightRecord::RecordIOResult FlightRecord::LoadRecordData( std::string const& _flightCode, int const _numSeats, std::string const& _timeOfDay, std::string const& _date, std::string const& _destination )
{
  //TODO: This function has an unhealthy number of magic numbers.

  // Initial validity checks.
  if ( !( _flightCode.size() == 5 &&
    _numSeats > 0 &&
    _timeOfDay.size() == 4 &&
    _date.size() == 8           )
    )
  {
    return RecordIOResult_Failure;
  }

  // Validate and store flight code.
  _flightCode.copy( m_flightCode, 5 );
  m_flightCode[5] = '\0';
  if ( !( isalpha( m_flightCode[0] ) &&
          isalpha( m_flightCode[1] ) &&
          isdigit( m_flightCode[2] ) &&
          isdigit( m_flightCode[3] ) &&
          isdigit( m_flightCode[4] )
     )  )
  {
    return RecordIOResult_Failure;
  }

  // Validate and store number of seats.
  if ( !( _numSeats > 0 &&
          _numSeats < sc_numSeatsMax ) )
  {
    return RecordIOResult_Failure;
  }
  m_numSeats = _numSeats;

  // Validate and store time/date.
  if ( !IsNumeric( _timeOfDay ) )
  {
    return RecordIOResult_Failure;
  }

  int hour   = atoi( _timeOfDay.substr( 0, 2 ).c_str() );
  int minute = atoi( _timeOfDay.substr( 2, 2 ).c_str() );
  if ( !( ( hour   >= 0 && hour   < 24 ) &&
    ( minute >= 0 && minute < 60 )    ) )
  {
    return RecordIOResult_Failure;
  }

  if ( !IsNumeric( _date ) )
  {
    return RecordIOResult_Failure;
  }

  int const day   = atoi( _date.substr( 0, 2 ).c_str() );
  int const month = atoi( _date.substr( 2, 2 ).c_str() );
  int const year  = atoi( _date.substr( 4, 4 ).c_str() );

  if ( !( day > 0 && day <= 31 &&
          month > 0 && month <= 12 &&
          year > sc_dateYearMin && year <= sc_dateYearMax
     )  )
  {
    return RecordIOResult_Failure;
  }

  m_time.SetTime( year, month, day, hour, minute );

	// Set destination
	m_destination =_destination;

  // Successfully loaded.
  return RecordIOResult_Success;
}

Record::RecordIOResult FlightRecord::PrintRecordData( std::ostream& _stream ) const
{
  char timeString[14];
  tm* tmTime = m_time.GetTm();
  ASSERT( tmTime );
  int ret = strftime( timeString, sizeof(char) * 14, "%H%M %d%m%Y", tmTime );

  if ( ret != 13 ) return FlightRecord::RecordIOResult_Failure;

  _stream << m_flightCode << " ";
  _stream << m_numSeats << " ";
  _stream << timeString << " ";
	_stream << m_destination << "\n";

  return Record::RecordIOResult_Success;
}

} // namespace AirlineRes